﻿namespace GTServices.WPF.Client
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel.Composition;
	using System.ComponentModel.Composition.Hosting;
	using System.ComponentModel.Composition.Primitives;
	using System.Linq;
    using System.Windows.Controls;
    using System.Windows;
    using System.Reflection;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using ICSharpCode.AvalonEdit;
    using ICSharpCode.AvalonEdit.Editing;
    using ICSharpCode.AvalonEdit.Highlighting;
    using ICSharpCode.AvalonEdit.Highlighting.Xshd;
    using System.IO;
    using System.Xml;

	using Caliburn.Micro;



	public class AppBootstrapper : Bootstrapper<IShell>
	{
		CompositionContainer container;
        
        Window _mainWindow;
		/// <summary>
		/// By default, we are configured to use MEF
		/// </summary>
		protected override void Configure() {
		    var catalog = new AggregateCatalog(
		        AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
		        );

			container = new CompositionContainer(catalog);

			var batch = new CompositionBatch();

			batch.AddExportedValue<IWindowManager>(new WindowManager());
			batch.AddExportedValue<IEventAggregator>(new EventAggregator());
			batch.AddExportedValue(container);
		    batch.AddExportedValue(catalog);

			container.Compose(batch);
            var baseLocator = ViewLocator.LocateForModelType;

            ConventionManager.AddElementConvention<MenuItem>(MenuItem.ItemsSourceProperty, "DataContext", "Click");


            ViewLocator.LocateForModelType = (x, y, z) =>
                {
                    const string  entityNamespace = "GTServices.Entities";
                    const string viewModelNamespace = "GTServices.WPF.Client.ViewModels";

                    var viewTypeName = x.FullName.Substring(0, x.FullName.IndexOf("`") < 0 ? x.FullName.Length : x.FullName.IndexOf("`")).Replace("Model", string.Empty);
                    
                    viewTypeName = viewTypeName.Remove(0, viewTypeName.LastIndexOf(".") + 1); 
                    
                    Type t = null;

                    if (x.Namespace.StartsWith(entityNamespace))
                    {
                        t = (from assembly in AssemblySource.Instance
                             from type in assembly.GetExportedTypes()
                             where type.FullName.EndsWith("." + x.Name + "View")
                             select type).FirstOrDefault();
                    }
                    else if (x.Namespace.StartsWith(viewModelNamespace))
                    {
                        t = (from assembly in AssemblySource.Instance
                             from type in assembly.GetExportedTypes()
                             where type.FullName.EndsWith("." + viewTypeName)
                             select type).FirstOrDefault();
                    }
                    else
                    {
                         //TODO: Log
                    }
                    

                    if(t != null)
                        return ViewLocator.GetOrCreateViewType(t);


                    return baseLocator(x, y, z);
                };
		}
        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            base.OnStartup(sender, e);
            _mainWindow = Application.MainWindow;
            _mainWindow.Closing += (x, y) =>
            {
                Execute.OnUIThread(() =>
                {
                    IShell shell = IoC.Get<IShell>();
                });
            };

            
            //Set the icon
            PngBitmapDecoder decoder = new PngBitmapDecoder(System.IO.File.Open("Images\\logo2.png", System.IO.FileMode.Open), BitmapCreateOptions.None, BitmapCacheOption.None);
            if (decoder != null && decoder.Frames[0] != null)
                _mainWindow.Icon = decoder.Frames[0] as ImageSource;
         

            //Set the title
            _mainWindow.Title = "CS²";

            
            //Load syntax highlights. 
            string dir = @".\Highlighting"; // Insert the path to your xshd-files.
            if(Directory.Exists(dir)){
                foreach(String file in Directory.GetFiles(dir)){
                    if(Path.GetExtension(file).ToLower().Contains("xshd")){
                        using (StreamReader sr = new StreamReader(File.Open(file, FileMode.Open)))
                        {
                            using (XmlReader reader = XmlReader.Create(sr))
                            {

                                var ret = HighlightingLoader.LoadXshd(reader);
                                var def = HighlightingLoader.Load(ret, HighlightingManager.Instance);

                                HighlightingManager.Instance.RegisterHighlighting(ret.Name, ret.Extensions.ToArray(), def);

                            }
                        }
                     
                    }
                }
            } 
        }
		protected override object GetInstance(Type serviceType, string key)
		{
			string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
			var exports = container.GetExportedValues<object>(contract);

			if (exports.Count() > 0)
				return exports.First();

			throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
		}

		protected override IEnumerable<object> GetAllInstances(Type serviceType)
		{
			return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
		}
        
		protected override void BuildUp(object instance)
		{
			container.SatisfyImportsOnce(instance);
		}

        protected override void OnExit(object sender, EventArgs e)
        {
            base.OnExit(sender, e);
            GTServices.Model.CoRoutine.Dispatcher.Instance.Dispose(); 
        }
	}
}
